//
// Created by admin on 2023/1/30.
//
#include "fd.h"
#include <unistd.h>
#include <fcntl.h>
#include "./error.h"
#include <sys/file.h>
#include "./log.h"
#include <termios.h>



namespace utils {

int open_port(const char *name) {
    int fd = ::open(name, O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd < 0) {
        throw IoError();
    }
    int ret = ::flock(fd, LOCK_EX | LOCK_NB);
    if (ret < 0) {
        log_e("file is lock");

        close_fd(fd);
        throw IllegalError("file is lock");
    }
    return fd;
}

void close_fd(int fd) noexcept {
    int ret = ::close(fd);
    if (ret < 0) {
        log_e("close fail:%s", current_err_msg());
    }
}

void set_port_attr(int fd, int baud_rate) {
    struct termios attr {};

    fcntl(fd, F_SETFL, 0);
    if (tcgetattr(fd, &attr) != 0) {
        throw IoError();
    }

    cfmakeraw(&attr);

    attr.c_cflag &= ~PARENB;
    attr.c_iflag &= ~(INPCK);

    attr.c_cflag &= ~CSTOPB;

    attr.c_cflag &= ~CSIZE;
    attr.c_cflag |= CS8;

    attr.c_cflag &= ~CRTSCTS;

    attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | NOFLSH | ISIG);

    attr.c_oflag &= ~(OPOST);

    int baud = B115200;

    switch (baud_rate) {
        case 9600: baud = B9600; break;
        case 115200: baud = B115200; break;
        case 38400: baud = B38400; break;
        default: throw IllegalError("not suppore baud rate"); break;
    }
    cfsetispeed(&attr, baud);
    cfsetospeed(&attr, baud);

    if (tcsetattr(fd, TCSANOW, &attr) != 0) {
        throw IoError();
    }
}














}

